<!--
 * @description: Composition API demo
 * @Author: lhr
 * @Date: 2020-12-01 14:31:35
 * @LastEditors: lhr
 * @LastEditTime: 2020-12-23 15:39:05
-->
<template>
  <h2>vue3 todoList</h2>
  <div>
    <div>
      <input type="text" v-model="todoValue" />
      <input type="button" @click="addTodo" value="添加" />{{ todoValue }}
    </div>
    <p>共{{ total }}个任务</p>
    <ul>
      <li v-for="(item, index) in data.todoList" v-bind:key="index">
        <span>{{ item }}</span>
        <button type="button" @click="deleteItem(index)">删除</button>
      </li>
    </ul>
  </div>
  <hr />
  <h2>toRefs &amp; toRef</h2>
  <div>
    <!-- <input type="text" v-model="obj.name" />{{ obj.name }}<br /> -->
    <input type="text" v-model="name" />{{ name }}
  </div>
  <hr />
  <h2>computed计算属性</h2>
  <div>
    <input type="text" v-model="firstName" />
    <input type="text" v-model="lastName" />
    <p>{{ fullName }}</p>
  </div>

  <h2>watch</h2>
  <div>
    <input type="text" v-model="firstName2" />
    <input type="text" v-model="lastName2" />
    <p>{{ fullName2 }}</p>
  </div>
  <h2>watchEffect</h2>
  <div>
    <input type="text" v-model="firstName3" />
    <input type="text" v-model="lastName3" />
    <p>{{ fullName3 }}</p>
  </div>
  <h2>setup的参数</h2>
  <hello-setup class="test" :text="name" @ok="ok">
    <p>我是内容哈哈哈</p>
  </hello-setup>
</template>

<script>
// import { reactive, computed, onMounted, ref, watch, watchEffect } from "vue";
// import { reactive, computed, onMounted, ref, watch, watchEffect, toRefs } from "vue";
// import { reactive, computed, onMounted, ref, watch, watchEffect, toRef } from "vue";
import { reactive, computed, onMounted, ref, watch, watchEffect, toRefs, toRef } from "vue";
import HelloSetup from '@/components/HelloSetup.vue'

// 输入框组件
const inputCom = function() {
  let todoValue = ref(""); // 基础类型使用ref定义
  onMounted(() => {
    console.log("input-mounted");
  });
  return {
    todoValue,
  };
};

// 列表组件
const listCom = function(todoValue) {
  let data = reactive({
    todoList: [],
  }); // 引用类型建议用reactive()定义
  let total = computed(() => data.todoList.length);

  // 点击添加按钮
  function addTodo() {
    if (todoValue.value.trim().length === 0) {
      alert("请先输入内容");
      return;
    }
    data.todoList.push(todoValue.value);
    todoValue.value = "";
  }

  // 点击删除按钮
  function deleteItem(index) {
    data.todoList.splice(index, 1);
  }
  watch(total, (newVal, oldVal) => {
    console.log("Composition API", oldVal, newVal);
  });

  onMounted(() => {
    console.log("list-mounted");
  });

  return {
    data,
    total,
    addTodo,
    deleteItem,
  };
};

// ref 组件
const refCom = function() {
  const obj = reactive({
    name: "测试reactive",
  });
  // let name = ref("测试ref");

  // let name = obj.name; // 这样定义不是响应式
  // let {name} = toRefs(obj); // toRefs获取引用
  let name = toRef(obj, "name"); // toRef获取引用

  return {
    obj,
    name,
  };
};

// 计算属性组件
const computedCom = function() {
  let firstName = ref("李");
  let lastName = ref("四");
  let fullName = computed(() => firstName.value + lastName.value);
  return {
    firstName,
    lastName,
    fullName,
  };
};

// watch组件
// const watchCom = function(){
//   let firstName2 = ref("张");
//   let lastName2 = ref("三");
//   let fullName2 = ref(firstName2.value + lastName2.value);

//   // 侦听单个数据源
//   watch(firstName2,(newVal,oldVal)=>{
//     fullName2.value = firstName2.value + lastName2.value
//     console.log(newVal,oldVal)
//   })

//   watch(lastName2,(newVal,oldVal)=>{
//     fullName2.value = firstName2.value + lastName2.value
//     console.log(newVal,oldVal)
//   })

//   // 侦听多个数据源
//   watch([firstName2,lastName2],([newF,newL],[oldF,oldL])=>{
//     fullName2.value = firstName2.value + lastName2.value
//     console.log(newF,newL,oldF,oldL)
//   })

//   return {
//     firstName2,
//     lastName2,
//     fullName2,
//   };
// }

const watchCom = function() {
  const person = reactive({
    firstName2: "张",
    lastName2: "三",
    fullName2: "张三",
  });

  // 侦听单个数据源
  watch(
    () => person.firstName2,
    (newVal, oldVal) => {
      person.fullName2 = person.firstName2 + person.lastName2;
      console.log(newVal, oldVal);
    }
  );

  watch(
    () => person.lastName2,
    (newVal, oldVal) => {
      person.fullName2 = person.firstName2 + person.lastName2;
      console.log(newVal, oldVal);
    }
  );

  // 此处需要写成一个函数的形式，不能直接监听person.firstName2
  watch(
    [() => person.firstName2, () => person.lastName2],
    ([newF, newL], [oldF, oldL]) => {
      person.fullName2 = person.firstName2 + person.lastName2;
      console.log(newF, newL, oldF, oldL);
    }
  );

  let { firstName2, lastName2, fullName2 } = toRefs(person);
  return {
    firstName2,
    lastName2,
    fullName2,
  };
};

// watchEffect组件
const watchEffectCom = function() {
  const person = reactive({
    firstName: "张",
    lastName: "三",
    fullName: "",
  });

  watchEffect(() => {
    person.fullName = person.firstName + person.lastName;
    console.log(person.firstName, person.lastName, person.fullName);
  });
  let {
    firstName: firstName3,
    lastName: lastName3,
    fullName: fullName3,
  } = toRefs(person);
  
  return {
    firstName3,
    lastName3,
    fullName3,
  };
};

export default {
  setup() {
    let { todoValue } = inputCom();
    let { data, total, addTodo, deleteItem } = listCom(todoValue);
    let { obj, name } = refCom();
    let { firstName, lastName, fullName } = computedCom();
    let { firstName2, lastName2, fullName2 } = watchCom();
    let { firstName3, lastName3, fullName3 } = watchEffectCom();

    function ok(){
      alert('子组件点击了ok')
    }
    return {
      todoValue,
      data,
      total,
      addTodo,
      deleteItem,
      obj,
      name,
      firstName,
      lastName,
      fullName,
      firstName2,
      lastName2,
      fullName2,
      firstName3,
      lastName3,
      fullName3,
      ok
    };
  },
  components: {
    HelloSetup
  }
};

/*
export default {
  // setup在beforeCreate之前
  setup() {
    let data = reactive({
      todoList: [],
    }); // 引用类型建议用reactive()定义
    let todoValue = ref(""); // 基本数据（数字、字符串、Boolean）类型建议用ref()定义为响应式
    let total = computed(() => data.todoList.length);

    function initList() {
      data.todoList = ["打扫卫生"];
    }

    // 点击添加按钮
    function addTodo() {
      if (todoValue.value.trim().length === 0) {
        alert("请先输入内容");
        return;
      }
      data.todoList.push(todoValue.value);
      todoValue.value = "";
    }

    // 点击删除按钮
    function deleteItem(index) {
      data.todoList.splice(index, 1);
    }

    onMounted(() => {
      initList();
    });

    watch(total, (oldVal, newVal) => {
      console.log("Composition API", oldVal, newVal);
    });

    // 模板里用到的需要返回
    return {
      todoValue,
      total,
      data,
      addTodo,
      deleteItem,
    };
  },
};
*/
</script>
